Nội dung: Lịch sử hình thành và vai trò của bare-metal khi phát triển hệ thống nhúng
Những yêu cầu mới về tính minh bạch dẫn đến những lựa chọn khác nhau, đặc biệt là an toàn và bảo mật.
Khi nhu cầu về an toàn và bảo mật ngày càng tăng trên các lĩnh vực ứng dụng như xe hơi, công nghiệp và điện toán đám mây, ngành công nghiệp bán dẫn đang tìm những cách tốt nhất để bảo vệ các hệ thống của nó. Câu hỏi lớn đặt ra là nên xây dựng hệ thống bảo mật và an toàn ở phần cứng, hoặc phần mềm, hoặc cả hai thì tốt hơn.
Câu trả lời vẫn chưa hoàn toàn rõ ràng, nhưng một trong những lựa chọn đang được xem xét là một thứ gì đó ở mức trung bình — phần mềm chạy trực tiếp trên chip, thay vì được viết vào giao diện lập trình ứng dụng (API) trong hệ điều hành. Lập trình bare metal bao gồm mọi thứ từ hệ điều hành thời gian thực (real-time operating systems) và driver cho đến các máy ảo Loại 1 (Type 1 Hypervisor). Bare metal cực kỳ nhanh và đáng tin cậy, vì nó không cần qua nhiều lớp trừu tượng phần mềm (software abstraction layers), nhưng lại khó phát triển với các chip hiện đại.
Colin Walls, nhà công nghệ phần mềm nhúng tại Mentor, Siemens Business, cho biết trong những ngày đầu phát triển hệ thống nhúng, phần mềm ít được chú trọng, và thường là thứ gì đó được bổ sung thêm. “Thông thường, nó được phát triển bởi chính kỹ sư đã thiết kế phần cứng, và tất nhiên mã của họ tương tác rất chặt chẽ với phần điện tử. Họ hiểu tất cả sắc thái hành vi của phần cứng, vì vậy nó không được coi là một thách thức khó”.
Khi các hệ thống phức tạp hơn, các chuyên gia phần mềm bắt đầu tham gia. Những chuyên gia này thường là kỹ sư có kiến thức và am hiểu về phần cứng, vì vậy họ khá hài lòng khi lập trình gần với phần cứng. Nhưng tính phức tạp ngày càng tăng đã khiến công việc này ngày càng khó.
“Khi độ phức tạp tăng lên, những kỹ sư phần mềm đơn lẻ đã trở thành một nhóm,” Walls nói. “Các thành viên trong nhóm sẽ có những chuyên môn khác nhau. Những người có kiến thức phần cứng tốt sẽ đóng gói chuyên môn đó thành những module phần mềm, để cung cấp một giao diện sạch và che giấu tính phức tạp của giao tiếp phần cứng. Các module này được gọi là driver.”
Với bộ vi xử lý (microprocessor) / vi điều khiển (microcontroller) ngày càng mạnh mẽ và bộ nhớ ngày càng lớn thì nhu cầu sử dụng một cấu trúc chương trình hợp lý đã thúc đẩy việc áp dụng hệ điều hành thời gian thực (RTOS) cho phép sử dụng mô hình đa tác vụ (multi-tasking model). Đó là một tiến trình tự nhiên để các driver trở thành một phần của RTOS.
Bare Metal Software
Khi phát triển một hệ thống nhúng, một quyết định cần sớm đưa ra là có nên sử dụng RTOS hay không. Nhiều kỹ sư rất ít suy nghĩ về vấn đề này vì họ đã quen với việc code trên đỉnh hệ điều hành. RTOS là code được viết trên bare metal và nó là một lựa chọn quan trọng đối với các nhóm thiết kế.
Cấu trúc đơn giản nhất cho một ứng dụng nhúng là một vòng lặp vô hạn (infinite loop) — làm gì đó, làm gì đó khác, làm gì đó khác nữa, sau đó lặp lại.
Sự đơn giản của code rất có ý nghĩa vì hành vi của nó khá dễ đoán. Vấn đề là mỗi phần của code phụ thuộc vào các phần khác của code để có khả năng chạy. Điều này sẽ trở thành rắc rối nếu code bị sửa đổi hoặc cập nhật. Trạng thái cân bằng do đó bị xáo trộn. Cấu trúc code không chia tỷ lệ. Cách tái cấu trúc phần mềm nhằm giảm sự phụ thuộc lẫn nhau (có lẽ hiển nhiên) là di chuyển một số đoạn code phản hồi phần cứng vào các hàm dịch vụ ngắt (Interrupt Service Routines – ISR). ISR nhỏ và nhanh, chủ yếu liên quan đến việc xếp hàng đợi các công việc cần thực hiện trong vòng lặp chính. Cấu trúc sẽ dễ mở rộng hơn (more scalable), nhưng dù sao điểm mấu chốt vẫn là tất cả code ứng dụng phải ‘hoạt động tốt’.
Ở đây, cấu trúc chương trình linh hoạt và có thể mở rộng nhất chính là mô hình đa tác vụ (multi-tasking) hoặc đa luồng (multi-threading), trong đó mỗi phần chức năng của phần mềm được code như một chương trình độc lập được cấp phát thời gian CPU bởi một bộ điều phối (scheduler) (xem Figure 2). Đó chính là một phần của RTOS.
Ngày càng có nhiều quan tâm đến việc tạo ra các hệ thống giám sát SoC mà đơn giản là bỏ qua những thứ như điều khiển vận hành (run control), đây là cách debug cổ điển đối với phần mềm chạy trên một bộ xử lý. Thay vào đó, họ theo dõi mà không can thiệp hệ thống trong thời gian thực, để không ảnh hưởng đến hành vi của hệ thống. Làm việc ở lớp bare metal, cùng với loại bỏ hệ điều hành, có thể là một lựa chọn.
Các thách thức và lựa chọn lập trình
Mặc dù tỉ lệ lớn nhất của thiết kế phần mềm nhúng hiện đại thường là sử dụng một hệ điều hành (OS) nào đó, nhưng trong một số trường hợp không dùng OS sẽ là một quyết định hợp lý – lập trình trên bare metal. Có những tình huống như ứng dụng đó cực kỳ đơn giản và có lẽ cần được triển khai trên một bộ xử lý cấp thấp. Và cũng có tình huống cần tận dụng mọi chu kỳ (cycle) CPU cho ứng dụng và chi phí quá cao cho một hệ điều hành là điều không chấp nhận được.
Trong cả hai trường hợp đều cần phải cân nhắc đến những cải tiến sau này của phần mềm. Nếu có khả năng phát triển hơn nữa, thì việc bắt đầu với một cấu trúc chương trình có thể mở rộng là một khoản đầu tư đáng giá.
“Dường như ngày càng có nhiều quan tâm đến vấn đề tiếp cận này”. Gajinder Panesar, CTO của UltraSoC nói: “Trong khi lập trình trên bare metal không phải dòng chính như hiện nay, một số công ty đang kiểm định bằng quá trình phân tích trong thực tế. Mục đích là quan sát và phát hiện sự bất thường khi hệ thống đang chạy, điều này rất cần thiết đối với xe tự hành nếu sự bất thường có thể gây ra sự cố liên quan đến an toàn”.
“Có nhiều người đang hướng tới cách đó, để có thể dùng các phép đo hoặc dữ liệu phong phú mà các bộ quan sát bare metal tạo ra và họ muốn ‘nhai’ dữ liệu đó rồi quyết định xem liệu có điều dị thường xảy ra hay không,” Panesar nói. “Bước tiếp theo sẽ là lấy dữ liệu đó ra và nói: ‘À, đây là lý do tại sao nó lại xảy ra. Là bởi vì ai đó đã làm điều này sớm hơn vài giây, hoặc nano giây’. Chủ yếu là các hệ thống có tính an toàn (safety) và tính toàn vẹn (integrity) cao, nơi nó sẽ được sử dụng cho những việc như đảm bảo hệ thống vận hành và hoạt động tốt như mong đợi, và đảm bảo hệ thống sẽ hoạt động liên tục sau đó.”
Điều này có thể cực kỳ hữu ích trong các ứng dụng an toàn và bảo mật. “Các trường hợp đơn giản như quan sát cách một bộ các thứ (things) trong một hệ thống đang trình diễn – ‘dàn nhạc giao hưởng’ giữa phần mềm và phần cứng cũng như diễn biến của nó,” ông nói. “Bạn có thể xem xét vấn đề này bằng cách lùi lại một chút và nói: ‘Cách hệ thống này hoạt động là bộ những thứ này phải nói chuyện với bộ những thứ khác và cần phải có sự tương tác này’. Nếu mô hình hoặc giai điệu này thay đổi một chút hoặc là lệch, chúng ta có thể nhận ra điều đó. Do đó chúng ta có thể phát hiện những điều nên xảy ra nhưng đã không xảy ra hoặc những điều đã xảy ra nhưng lại không nên xảy ra. Ngoài ra, chúng ta còn có thể xem khi nào mọi thứ bắt đầu bị treo. Thử tưởng tượng nó là một giai điệu hoặc một bộ các thứ theo quy tắc, khi có một nốt sáng hoặc khi giai điệu thay đổi, lời nhạc vẫn giống nhau nhưng giai điệu đã khác. Ví dụ khi có pixel bị kẹt trong ứng dụng xe hơi, bằng cách quan sát những gì đang xảy ra trong SoC và giao tiếp giữa những thứ như đầu vào camera và bộ nhớ, chúng ta có thể phán đoán liệu camera đó có bị kẹt một số pixel hay không.”
Điều này có thể được thực hiện hoàn toàn bằng phần mềm, nhưng nó yêu cầu phần mềm chạy trong stack để phát hiện. Mối quan tâm lớn ở đây là độ trễ và thời gian cần thiết để phát hiện ra điều bất thường, mà phần mềm gần phần cứng lại tương tác nhanh hơn phần mềm đợi trong stack.
Panesar nói: “Thật thú vị, bạn không nhất thiết phải biết những gì bạn đang tìm kiếm để bắt đầu. Bạn nhận ra rằng SoC này sẽ xài được, chẳng hạn như quản lý động cơ của một chiếc xe hơi, và bạn biết tập hợp các quyền truy cập hoặc chuỗi các giao dịch sẽ diễn ra, và bạn bắt đầu. Nhưng sau đó bạn nhận ra rằng thật ra nó được kết nối với một cái gì đó như CAN bus hoặc automotive Ethernet, vì vậy nó không có giao diện. Và nhân tiện, đầu kia của Ethernet là một bảng điều khiển người dùng (user console) dùng cho thông tin và giải trí (infotainment), và tại sao nó lại truy cập vào hệ thống quản lý động cơ? Nó có hợp lý không? Vì vậy, trong thời gian chạy, bạn có thể đảm bảo rằng chỉ những giao tiếp này mới có thể truy cập vào SoC. Và bạn có thể từng bước xây dựng nó mà không cần quay lại SoC, cũng không cần phải thay đổi phần mềm ứng dụng đang chạy”.
Thị trường driver
Trong thế giới xe hơi, các tiêu chuẩn như ISO 26262 là tiên quyết. Nếu bạn không tuân theo các tiêu chuẩn đó, thì bạn không thể bán chip của mình vào một hệ thống cụ thể.
Frank Schirrmeister, giám đốc nhóm cấp cao về quản lý sản phẩm và tiếp thị cho mô phỏng, tạo mẫu dựa trên FPGA và hỗ trợ phần cứng / phần mềm tại Cadence cho biết: “Đó thực sự là nơi mà nhu cầu lập trình bare metal cho ô tô bắt đầu. Nó bắt nguồn từ tỷ số thất bại mà bạn thấy đối với một số thành phần nhất định trong hệ thống. Nếu bạn nhìn vào chiếc xe, có một vài tỷ số về số lần được phép sai. Điều đó ảnh hưởng xuống các thành phần bên dưới — số lần chúng được phép sai. Và sau đó là những phép nhân các xác suất với nhau. Vấn đề là bạn càng nhân lên nhiều lần thì xác suất của một trong hai bị sai càng lớn.”
Nhiều nhóm kỹ sư đã xem xét các khía cạnh liên quan đến an toàn ở cấp độ chip, nơi họ kiểm tra xem liệu hệ thống có còn hoạt động an toàn hay không, nếu có bit bị kẹt ở một mức độ nhất định.
“Trong bối cảnh đó, chúng tôi cũng đang kiểm tra các hạng mục liên quan đến phần mềm ở cấp độ đó,” Schirrmeister nói. “Và tiếp theo thực sự là bare metal. Đây là lớp đầu tiên tiếp xúc với phần an toàn chức năng trong chip thông qua một phần mở rộng của các công cụ mô phỏng lỗi, dùng để kiểm tra xem hệ thống sẽ làm gì nếu một node nhất định bị kẹt ở bit 0 hoặc bị kẹt ở bit 1. Vì vậy, trong trường hợp ô tô, liên quan đến tất cả các định nghĩa của ISO 26262. Phần mềm đóng một vai trò trong đó nó chạy trên một bộ xử lý ở cấp độ bare metal. Bạn sẽ muốn tìm hiểu xem liệu hệ thống có trở lại trạng thái an toàn hay không. Vấn đề chính này biến thành việc lập kế hoạch cho các chiến dịch kiểm lỗi, đó là những thứ bạn thực sự muốn kiểm tra, bởi vì bạn muốn kiểm tra xem phần cụ thể này của con chip của tôi có bị lỗi không, liệu hệ thống của tôi có đi vào trạng thái an toàn hay không?”
Và trong khi điều này cần được tính đến ở cấp độ kiến trúc hoặc trước từ trong quá trình thiết kế, thì cũng có một số cơ chế cho phép hệ thống trở lại trạng thái an toàn. Chúng được thực hiện ở cấp thấp hơn một chút.
Schirrmeister nói: “Đối với một hệ thống phần mềm, bạn muốn nó không chỉ gặp sự cố, mà còn muốn nó chuyển sang trạng thái an toàn và đó là nơi mà lớp bare metal của phần mềm có thể hữu ích để chỉ ra cụ thể. Điều gì sẽ xảy ra nếu chương trình này bị lỗi? Hoặc nếu phần cứng bị lỗi vào thời điểm này, ta sẽ bị kẹt trong một hàm xử lý ngắt (interrupt routine) hoặc cái gì khác nữa. Do đó cần phải đưa hệ thống vào trạng thái an toàn và dự đoán được.”
Rủi ro và lợi ích an toàn
Mặc dù những lợi ích đối với khả năng hiển thị ở cấp độ bare metal đã rõ ràng, nhưng vẫn có những lo ngại về khả năng truy cập chip ở các cấp độ khác nhau. Một số chuyên gia trong ngành tự hỏi liệu các lỗ hổng có thể được giới thiệu đi cùng hay không.
Đây là một lĩnh vực mà việc xác minh chính thức có thể đóng vai trò trọng yếu, vì nó có thể khám phá ra những vấn đề tiềm ẩn trong một hệ thống phức tạp mà có thể không minh bạch.
Sergio Marchese, giám đốc tiếp thị kỹ thuật tại OneSpin Solutions: “Bạn đang xem xét các trường hợp sử dụng chưa rõ mà hầu hết các xác minh chức năng được xây dựng cho các trường hợp sử dụng. Tôi từng tìm thấy một lỗi trong lõi Arm. Hướng dẫn được đánh dấu là hợp lệ, trong khi nó không hợp lệ. Người thiết kế, tất nhiên rất, rất bận rộn nói với tôi rằng đây là một kịch bản điên rồ sẽ không xảy ra. ‘Đây không phải là trường hợp sử dụng được khuyến nghị. Nó không phải là thứ mà một người bình thường sẽ sử dụng, vì vậy nó an toàn. Tôi không có thời gian để giải quyết việc này. Tôi cần sửa các lỗi có thể tạo ra các mớ hỗn độn ở trường hợp sử dụng của tôi’. Nhưng khi nói đến bảo mật, hãy bàn đến lỗi này. Nó có thể dẫn đến một lỗ hổng bảo mật, bởi vì đó chính là thứ một kẻ thù đang tìm kiếm. Kẻ thù không tìm kiếm các trường hợp sử dụng thông thường. Hắn đang tìm kiếm những thứ vui nhộn có thể thỏa hiệp với tính bảo mật của chip. Vì vậy, đó là một khía cạnh bảo mật của nó. Tiếp theo, tôi nghĩ về các vấn đề, và có hai loại. Một là bản thân bảo mật, có nghĩa là: ‘Hãy nói rằng, chúng tôi sẽ không bao giờ xây dựng điều này thông qua những sai lầm thực, hoặc những sai lầm có thể xuất hiện ở cấp kiến trúc, ở cấp độ triển khai, lỗi chức năng, hoặc bất cứ thứ gì’. là những lỗ hổng do những sai lầm nguy hiểm”.
Panesar nhấn mạnh ý định không thay thế các phương pháp bảo mật thông thường. Đúng hơn, nó là để tăng cường các phương pháp đó. Ông nói: “Những thứ như mã hóa khóa công khai (public key encryption), v.v., tất cả đều phải có”. “Trong một ví dụ điển hình, có thể một SoC đã bị hack bằng cách nào đó và ai đó đã điều khiển để tải xuống một số phần mềm đào tiền điện tử (crypto mining software). Làm thế nào để bạn phát hiện ra điều đó? Bạn có thể phát hiện điều này bằng cách kiểm tra lưu lượng bất thường của CPU. Bạn có thể phát hiện điều này bằng cách hiểu hoặc theo dõi. Có một số cách bạn có thể quan sát việc sử dụng CPU, ngay cả trong chu kỳ nghỉ (idle period) khi không có hoạt động nào. Ngay cả khi ô tô không di chuyển, thông tin vẫn có thể được truyền qua một kênh bảo mật, có thể là kênh SSH, đến hệ thống giám sát nào đó”.
Cách tiếp cận này cũng hiệu quả để xác định ramsomware (một loại phần mềm độc hại được thiết kế để chặn quyền truy cập vào hệ thống máy tính cho đến khi một khoản tiền được thanh toán). “Bạn phải phát hiện ra hoạt động bất thường này khi hệ thống có dấu hiệu nghỉ (idle) và thông báo cho mọi người,” ông nói. “Dữ liệu này được gửi định kỳ trong các hệ thống luôn được kết nối. Ngành công nghiệp ô tô sẽ thực hiện giao tiếp giữa các xe với xe và chúng sẽ luôn được kết nối với nhau để đảm bảo rằng ô tô không bị hỏng đột ngột và họ không nhận được bất cứ tín hiệu nào. Vì vậy có thể khai thác kết nối đó. Bạn có thể gửi định kỳ một thông số nhịp tim. Và đột nhiên, bạn sẽ thấy một CPU hoạt động đến 90%, trong khi thực ra nó đang bị kẹt trong một bãi đỗ xe”.
Phần kết luận
Rõ ràng, còn nhiều việc phải làm và các giải pháp vẫn đang được phát triển — đặc biệt là về bảo mật.
Marchese nói: “Lĩnh vực này vẫn đang được xây dựng rất ít. Làm thế nào để bạn đánh đổi kiến trúc bảo mật, có thể nói, với sức mạnh, với diện tích, với sự phức tạp, với công việc thiết kế và kỹ thuật bổ sung? Sự an toàn, theo một nghĩa nào đó, dễ dàng hơn vì bạn có một kẻ thù nhìn thấy được. Bạn mô hình hóa các lỗi ngẫu nhiên của mình để nói rằng: ‘Tôi muốn thấy các kiểu lỗi này trong kiểu logic này’. Bạn có thể định lượng nó. Đó là công việc khá khó khăn, nhưng ít nhất bạn biết chính xác loại kẻ thù mà bạn đang phòng thủ. Với bảo mật thì không như vậy. Bạn có một số sự thật đã biết, nhưng cuối cùng những thứ tinh vi mà bạn không biết lại là những thứ bạn muốn bảo vệ, vì vậy mọi thứ trở nên phức tạp hơn. Ngay cả khi bạn thêm lập luận mới, bạn cần phải thận trọng để không thêm lỗ hổng mới bởi vì với bảo mật, mọi thứ khá điên rồ”.
Lập trình bare metal có thể là sự thỏa hiệp tối hậu giữa phần cứng và phần mềm, nhưng nó đòi hỏi sự hiểu biết sâu sắc về cả hai ngay từ đầu của quá trình thiết kế. Vì vậy, mặc dù có những lợi ích rõ ràng, nhưng công việc này không hề dễ dàng.